#pragma once


/**
*  sqlite3 封装类
*  jiegemena
*  2022-09-22
*  防注入 { "and ","exec ","insert ","select ","delete ","update ","count ","*","%","chr","mid" ,"master ","truncate ","char ","declare ",";","or ","-","+",",","drop ","\'"};
*  v1.0.4-20220925
*  https://gitee.com/jieguomena/sqlite3-entity.git
*/


#include <sqlite3.h>
#include <memory>
#include <string>
#include <mutex>
#include <vector>
#include <map>
#include <iostream>
#include <algorithm>

using namespace std;

enum class sqliteEFType
{
    type_int = 0,
    type_str = 1,
    type_double = 2,
    type_null = 3
};

struct sqliteEFVal
{
    sqliteEFType sType = sqliteEFType::type_str;
    int int_val = 0;
    string str_val;
    double d_val = 0;
    string null_val = "NULL";
};

class sqliteEFCols
{
public:
    typedef map<string, sqliteEFVal>::iterator iterator;
public:
    sqliteEFCols();
    ~sqliteEFCols();

    sqliteEFVal* get(string key);

    void add(string key,int val);
    void add(string key, double val);
    void add(string key, string val);
    void add(string key, sqliteEFVal val);

    iterator& begin();
    iterator& end();

    void clear();
    int size();

private:
    map<string, sqliteEFVal> m_clos;
    iterator m_clos_it;
};

typedef vector<sqliteEFCols> sqliteEFRows;

class sqliteEF
{
private:
    sqlite3* db = NULL;
    mutex lock_mutex;

private:
    sqliteEF();
    ~sqliteEF();

    void dealBakVal(sqlite3_stmt* pStmt,int index,sqliteEFVal &out_ef);

    static sqliteEF m_sqliteEF;
public:
    void test();
    static void init(string dbName);


    string m_dbName;

    sqliteEFCols find(string sql);
    sqliteEFRows findAlls(string sql);
    int exec(string sql);

    static sqliteEF* GetClient() {
        if(m_sqliteEF.m_dbName.size() == 0)
        {
            throw "sqliteEF must init";
            return &m_sqliteEF;
        }
        
        return &m_sqliteEF;
    };
};

class sqliteEFInPars
{
public:
    sqliteEFInPars();
    ~sqliteEFInPars();

    void add(int par);
    void add(string par);
    void add(double par);
    int size();
    string at(int index);

    void clear();

    const string operator[](size_t pos) const
    {
        return m_squery[pos];
    }

    bool getCheckPar() { return m_isCheck; }

    static bool CheckPare(string a);
private:
    vector<string> m_squery;
    bool m_isCheck = true;
    bool checkPar(string a);
};

class sqliteEFModel
{
private:
    string sqlstr;
    string m_tableName;

    string toParCols(sqliteEFCols swhere, string checkWhere = "",string link = " and ");
    string getValFromEFVal(sqliteEFVal val);
public:
    sqliteEFModel(string sqlstr = "");
    sqliteEFModel(string sqlstr, string table);
    ~sqliteEFModel();

    static void outStr(sqliteEFRows rows);
    static void outStr(sqliteEFCols cols);
    static void init(string dbName) {
        sqliteEF::init(dbName);
    };
    string toSqlStr() { return sqlstr; };
    sqliteEFModel table(string tableName);
    sqliteEFModel select(string select = "*");
    sqliteEFModel where(string swhere);
    sqliteEFModel where(sqliteEFCols swhere,string checkWhere="");
    sqliteEFModel where_or(sqliteEFCols swhere, string checkWhere = "");
    sqliteEFModel update(string set);
    sqliteEFModel update(sqliteEFCols swhere, string checkWhere = "");
    sqliteEFModel orderEsc(string sortstr);
    sqliteEFModel orderDesc(string sortstr);
    sqliteEFModel pages(int page=1,int pagesize=10);
    sqliteEFModel del();
    sqliteEFModel sql(string sql);

    // （isCheckWhere=false，swhere 不在 checkWhere集合，反之在）
    sqliteEFModel insert(sqliteEFCols swhere, string checkWhere = "",bool isCheckWhere = true);

    sqliteEFCols find();
    sqliteEFRows findAlls();


    sqliteEFCols find(sqliteEFInPars pars);
    sqliteEFRows findAlls(sqliteEFInPars pars);

    int exec();
    int exec(sqliteEFInPars pars);
};




